package com.rpc.netty.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * @author 何章怀晓 hezhanghuaixiao
 * @version V1.0
 * @desc
 */
public class NIOServer {

  private static final int PORT = 8888;

  private Selector selector;

  private ServerSocketChannel serverSocketChannel;

  public NIOServer() throws IOException {
    selector = Selector.open();

    serverSocketChannel = serverSocketChannel.open();

    serverSocketChannel.socket().bind(new InetSocketAddress(PORT));

    serverSocketChannel.configureBlocking(false);

    serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
  }

  /**
   * @describe 等待客户端连接
   * @author 何章怀晓 hezhanghuaixiao
   * @date 2022/2/28  12:37
   * @other
   */

  public void linsten() {
    System.out.println("服务器已启动，等待连接");
    try {
      while (true) {
        int select = selector.select();

        if (select > 0) {
          Set<SelectionKey> selectionKeys = selector.selectedKeys();
          Iterator<SelectionKey> iterator = selectionKeys.iterator();
          while (iterator.hasNext()) {
            SelectionKey key = iterator.next();

            if (key.isAcceptable()) {
              connEvent();
            }

            if (key.isReadable()) {
              readEvent(key);
            }
          }

          iterator.remove();
        }
      }

    } catch (Exception e) {
      e.printStackTrace();
    }


  }

  public void connEvent() {
    try {
      SocketChannel socketChannel = serverSocketChannel.accept();

      socketChannel.configureBlocking(false);

      socketChannel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));

      System.out.println(socketChannel.getLocalAddress() + "上线啦...");
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  public void readEvent(SelectionKey key) {
    SocketChannel socketChannel = null;
    try {
      socketChannel = (SocketChannel) key.channel();
      ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
      int read = socketChannel.read(byteBuffer);
      if (read > 0) {
        String msg = new String(byteBuffer.array());

        System.out.println("客户端" + socketChannel.getRemoteAddress() + "发来信息" + msg);

      }
    } catch (Exception e) {
      try {
        System.out.println(socketChannel.getRemoteAddress() + "下线了");
        //必须关闭
        key.cancel();
        socketChannel.close();
      } catch (Exception ep) {
        ep.printStackTrace();
      }
    }
  }


  public static void main(String[] args) throws IOException {
    NIOServer nioServer = new NIOServer();
    nioServer.linsten();

  }
}
